package com.xiwen.plugin.mybatisplus.generator.util;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.BeetlTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import com.xiwen.plugin.mybatisplus.config.Config;

import java.util.ArrayList;
import java.util.List;

/**
 * @author xiwen
 * @since 2019-04-17 12:04
 */
public class GeneratorUtils {

    /**
     * 数据连接信息
     * @param dbType 数据库类型
     * @param dbUrl 连接地址
     * @param username 用户名
     * @param password 密码
     * @param driver 驱动
     * @return DataSourceConfig
     */
    private static DataSourceConfig dataSourceConfig(DbType dbType, String dbUrl, String username, String password, String driver) {
        return new DataSourceConfig()
                .setDbType(dbType)
                .setUrl(dbUrl)
                .setUsername(username)
                .setPassword(password)
                .setDriverName(driver)
                ;
    }

    // 配置
    private static GlobalConfig globalConfig() {
        return new GlobalConfig()
                .setAuthor(Config.AUTHOR)
                .setOutputDir(Config.OUTPUT_DIR)
                .setFileOverride(true) // 是否覆盖已有文件
                .setOpen(true) // 是否打开输出目录
                .setDateType(DateType.TIME_PACK) // 时间采用java 8，（操作工具类：JavaLib => DateTimeUtils）
                .setActiveRecord(true)// 不需要ActiveRecord特性的请改为false
                .setEnableCache(false)// XML 二级缓存
                .setBaseResultMap(false)// XML ResultMap
                .setBaseColumnList(false)// XML columList
                .setKotlin(false) //是否生成 kotlin 代码
                // 自定义文件命名，注意 %s 会自动填充表实体属性！
                .setEntityName(Config.FILE_NAME_MODEL)
                .setMapperName(Config.FILE_NAME_DAO)
              /*  .setXmlName(Config.FILE_NAME_XML)*/
                .setServiceName(Config.FILE_NAME_SERVICE)
                .setServiceImplName(Config.FILE_NAME_SERVICE_IMPL)
                .setControllerName(Config.FILE_NAME_CONTROLLER)
                .setIdType(IdType.UUID) // 主键类型
                .setSwagger2(Config.SWAGGER_SUPPORT); // model swagger2

    }


    private static StrategyConfig strategyConfig(String [] tablePrefixes, String [] tableNames, String [] fieldPrefixes, String [] excludeTableNames) {
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setCapitalMode(true) ; // 全局大写命名 ORACLE 注意
        strategyConfig.setSkipView(false) ;  // 是否跳过视图
        strategyConfig.setTablePrefix(tablePrefixes) ;// 此处可以修改为您的表前缀(数组)
        strategyConfig.setFieldPrefix(fieldPrefixes) ; // 字段前缀
        strategyConfig.setNaming(NamingStrategy.underline_to_camel) ; // 表名生成策略
        strategyConfig.setInclude(tableNames) ;//修改替换成你需要的表名，多个表名传数组
        strategyConfig.setExclude(excludeTableNames) ; // 排除生成的表
        strategyConfig.setEntityLombokModel(true) ; // lombok实体
        strategyConfig.setEntityColumnConstant(false) ; // 【实体】是否生成字段常量（默认 false）// 可通过常量名获取数据库字段名 // 3.x支持lambda表达式
        strategyConfig.setLogicDeleteFieldName(Config.FIELD_LOGIC_DELETE_NAME);// 逻辑删除属性名称
        strategyConfig.setVersionFieldName(Config.FIELD_VERSION_NAME)  ;// 乐观锁字段名
        strategyConfig.setEntityTableFieldAnnotationEnable(true) ; // 开启实体字段注解
        return strategyConfig;

    }

    // 包信息配置
    private static PackageConfig packageConfig(String packageName) {
        return new PackageConfig()
                .setParent(packageName)
                .setController(Config.PACKAGE_NAME_CONTROLLER)
                .setEntity(Config.PACKAGE_NAME_MODEL)
                .setMapper(Config.PACKAGE_NAME_DAO)
                /*.setXml(Config.DIR_NAME_XML)*/
                .setService(Config.PACKAGE_NAME_SERVICE)
                .setServiceImpl(Config.PACKAGE_NAME_SERVICE_IMPL);
    }



    /**
     * 获取模板引擎
     * @return 模板引擎 {@link AbstractTemplateEngine}
     */
    private static AbstractTemplateEngine getTemplateEngine() {
        String templateEngine = Config.TEMPLATE_ENGINE;
        switch (templateEngine) {
            case "velocity":
                return new VelocityTemplateEngine();
            case "freemarker":
                return new FreemarkerTemplateEngine();
            case "beetl":
                return new BeetlTemplateEngine();
        }
        return new VelocityTemplateEngine();
    }

    /**
     * 执行器
     */
    public static void execute(DbType dbType, String dbUrl, String username, String password, String driver,
                               String [] tablePrefixes, String [] tableNames, String packageName, String [] fieldPrefixes, String [] excludeTableNames) {
        GlobalConfig globalConfig = globalConfig();
        //项目根目录  不可修改
        String projectPath = System.getProperty("user.dir");
        System.out.println("项目根路径"+projectPath);
        DataSourceConfig dataSourceConfig = dataSourceConfig(dbType, dbUrl, username, password, driver);
        StrategyConfig strategyConfig = strategyConfig(tablePrefixes, tableNames, fieldPrefixes, excludeTableNames);
        PackageConfig packageConfig = packageConfig(packageName);
//      InjectionConfig injectionConfig = injectionConfig(packageConfig);
        AbstractTemplateEngine templateEngine = getTemplateEngine();
        AutoGenerator autoGenerator = new AutoGenerator();
        autoGenerator.setGlobalConfig(globalConfig);
        autoGenerator.setDataSource(dataSourceConfig);
        autoGenerator.setStrategy(strategyConfig);
        autoGenerator.setPackageInfo(packageConfig);
        autoGenerator.setTemplateEngine(templateEngine);
                //.setCfg(injectionConfig)

        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
            }
        };

        List<FileOutConfig> focList = new ArrayList<FileOutConfig>();

        focList.add(new FileOutConfig("/templates/vm/java/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/src/main/resources/mapper/" + tableInfo.getName()
                        + "/" + tableInfo.getName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        focList.add(new FileOutConfig("/templates/vm/html/list.html.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/src/main/resources/templates/admin/index/" + tableInfo.getName()
                        + "/" + tableInfo.getName() + "-list.html";
            }
        });

        focList.add(new FileOutConfig("/templates/vm/html/from.html.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/src/main/resources/templates/admin/index/" + tableInfo.getName()
                        + "/" + tableInfo.getName() + "-from.html";
            }
        });

        cfg.setFileOutConfigList(focList);
        autoGenerator.setCfg(cfg);

        TemplateConfig template = new TemplateConfig();
        template.setController("/templates/vm/java/controller.java.vm");
        template.setEntity("/templates/vm/java/entity.java.vm");
        template.setService("/templates/vm/java/service.java.vm");
        template.setServiceImpl("/templates/vm/java/serviceImp.java.vm");
        template.setMapper("/templates/vm/java/dao.java.vm");
        template.setXml(null);
        autoGenerator.setTemplate(template);
        autoGenerator.execute();
    }

}
